package redis

import (
	"GoWebBluebell/models"
	"strconv"
	"time"

	"github.com/go-redis/redis"
)

func getPIDsFormKey(key string, page, size int64) ([]string, error) {
	// 2. 确定查询的索引起始点 (start为0 end为2时 redis查询会输出012)
	start := (page - 1) * size
	end := start + size
	// 3. ZREVRANGE 从大到小查询指定数量的元素
	return rdb.ZRevRange(key, start, end).Result()
}

func GetPostIDsInOrder(p *models.ParamPostList) ([]string, error) {
	//从redis获取pid
	// 1. 根据携带的order参数
	key := getRedisKey(KeyPostTimeZSet)
	if p.Order == models.OrderScore {
		key = getRedisKey(KeyPostScoreZSet)
	}

	return getPIDsFormKey(key, p.Page, p.Size)
}

// GetPostVoteData 根据pids查询每篇帖子投赞成票的数据
func GetPostVoteData(pids []string) (data []int64, err error) {
	// data = make([]int64, 0, len(pids))
	// for _, pid := range pids {
	// 	key := getRedisKey(KeyPostVotedZSetPF + pid)
	// 	// 查找key中分数是1的元素的数量 -> 统计每篇帖子赞成票数量
	// 	v := rdb.ZCount(key, "1", "1").Val() // 最小值和最大值都为1, 统计里边1的数量
	// 	data = append(data, v)
	// }

	// 使用pipelint 一次发送多条命令, 减少RTT
	pipeline := rdb.Pipeline()
	for _, pid := range pids {
		key := getRedisKey(KeyPostVotedZSetPF + pid)
		pipeline.ZCount(key, "1", "1")
	}
	cmders, err := pipeline.Exec()
	if err != nil {
		return nil, err
	}
	data = make([]int64, 0, len(cmders))
	for _, cmder := range cmders {
		v := cmder.(*redis.IntCmd).Val()
		data = append(data, v)
	}
	return
}

// GetCommunityPostIDsInOrder 按社区查询pids
func GetCommunityPostIDsInOrder(p *models.ParamPostList) ([]string, error) {
	orderKey := getRedisKey(KeyPostTimeZSet)
	if p.Order == models.OrderScore {
		orderKey = getRedisKey(KeyPostScoreZSet)
	}
	// 社区的key
	cKey := getRedisKey(KeyCommunyityZSetPF + strconv.Itoa(int(p.CommunityID)))

	// 利用缓存key减少zinterstore执行次数
	key := orderKey + strconv.Itoa(int(p.CommunityID))
	if rdb.Exists(key).Val() < 1 { //因为一开始算错了导致后面都不进这个if
		//不存在, 需要计算
		pipeline := rdb.Pipeline()
		pipeline.ZInterStore(key, redis.ZStore{
			Aggregate: "MAX",
		}, cKey, orderKey) // zinterstore计算 保存的地址是拼接处的缓存key, 聚合函数为求最大值MAX 聚合社区的key和post:score:或time:
		pipeline.Expire(key, 60*time.Second) //设置key的过期时间(60秒内不会再次执行, 利用缓存key减少执行次数)
		_, err := pipeline.Exec()
		if err != nil {
			return nil, err
		}
	}
	return getPIDsFormKey(key, p.Page, p.Size)
}
